/*
 * Copyright (C) 2013 by KB3ZYT Richard Nash
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef _GPS_H
#define _GPS_H

#include <Arduino.h>
#include <SoftwareSerial.h>

// different commands to set the update rate from once per ten seconds (0.1 Hz) to 10 times a second (10Hz)
#define PMTK_SET_NMEA_UPDATE_POINT1HZ  "$PMTK220,10000*2F"
#define PMTK_SET_NMEA_UPDATE_POINT2HZ  "$PMTK220,5000*1B"
#define PMTK_SET_NMEA_UPDATE_POINT5HZ  "$PMTK220,2000*1C"
#define PMTK_SET_NMEA_UPDATE_1HZ  "$PMTK220,1000*1F"
#define PMTK_SET_NMEA_UPDATE_5HZ  "$PMTK220,200*2C"
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"

#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C"
#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"

// turn on only the second sentence (GPRMC)
#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on just GGA
#define PMTK_SET_NMEA_OUTPUT_GGA "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on GPRMC and GGA
#define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn on ALL THE DATA
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn off output
#define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"

// standby command & boot successful message
#define PMTK_STANDBY "$PMTK161,0*28"
#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*3"  // Not needed currently
#define PMTK_AWAKE "$PMTK010,002*2D"

// ask for the release and version
#define PMTK_Q_RELEASE "$PMTK605*31"

// how long to wait when we're looking for a response
#define MAXWAITSENTENCE 5

// Return values for what sentence was just parsed
#define PARSE_NONE_RECEIVED 0
#define PARSE_ERROR 1
#define PARSED_SOMETHING 2

// Simulate the GPS information
//#define SIMULATE

class GPS {
public:
    GPS(SoftwareSerial *); // Constructor when using SoftwareSerial
    void init(uint16_t);
    void sendCommand(const char*);
    uint8_t recieveGPSSentence();
    
    uint8_t hour, minute, seconds, year, month, day;
    float latitude; // In degrees (no funny degrees and fractional minutes)
    float longitude; // In degrees
    float altitude; // In meters
    float speed, angle;
    boolean fix;
    uint8_t fixquality, satellites;
    
private:
    uint8_t parseGGA(const char*);
    uint8_t parseRMC(const char*);
    uint8_t parse(const char*);
    uint8_t recieve(char*, int);
    float degreesAndFractionalMinutesToDegrees(float, char);
    SoftwareSerial *gpsSwSerial;
    
#ifdef SIMULATE
    long millisSinceLastSend;
    int simCount;
#endif
};


#endif
